

import java.io.PrintStream;
import java.util.ArrayList;

import pluginUtils.Vector2D;
import pluginUtils.Vertex;

public class GeodeGenerator {

	/**
	 * @param args
	 */
	private class Face{
		private Vertex v1,v2,v3;

		public Face(Vertex v1, Vertex v2, Vertex v3) {
			super();
			this.v1 = v1;
			this.v2 = v2;
			this.v3 = v3;
		} 
		
		public String toString(){
			String s="<"+theVertices.indexOf(v1)+","+theVertices.indexOf(v2)+","+theVertices.indexOf(v3)+">"; 
			return s; 
		}
		
	}
	
	
	private ArrayList<Vertex> theVertices=new ArrayList<Vertex>();
	private ArrayList<Face> theFaces=new ArrayList<Face>();
	
	
	/*
	public GeodeGenerator(){
		double r=1/Math.sqrt(3); 
		Vertex v0=new Vertex(r,r,r);theVertices.add(v0);  
		Vertex v1=new Vertex(r,-r,-r);theVertices.add(v1);   
		Vertex v2=new Vertex(-r,r,-r);theVertices.add(v2);  
		Vertex v3=new Vertex(-r,-r,r);theVertices.add(v3);  
		
		
		
		Face f0=new Face(v0,v1,v2); theFaces.add(f0); 
		Face f1=new Face(v0,v2,v3);theFaces.add(f1); 
		Face f2=new Face(v0,v1,v3);theFaces.add(f2); 
		Face f3=new Face(v1,v2,v3); theFaces.add(f3); 
		
	}
	*/
	
	private double phi=(1+Math.sqrt(5))/2;
	private double r=1+phi*phi; 
	private double k=Math.sqrt(10+2*Math.sqrt(5))/2; 
	private double ra=k/r; 
	private double pr=k*phi/r;
	private double angle=180*Math.atan2(1,phi)/Math.PI; 
	
	public GeodeGenerator(){
		
		Vertex v0=new Vertex(0,pr,ra);theVertices.add(v0);  
		Vertex v1=new Vertex(0,pr,-ra);theVertices.add(v1);   
		Vertex v2=new Vertex(0,-pr,ra);theVertices.add(v2);  
		Vertex v3=new Vertex(0,-pr,-ra);theVertices.add(v3);  
		Vertex v4=new Vertex(ra,0,pr);theVertices.add(v4);  
		Vertex v5=new Vertex(ra,0,-pr);theVertices.add(v5);   
		Vertex v6=new Vertex(-ra,0,pr);theVertices.add(v6);  
		Vertex v7=new Vertex(-ra,0,-pr);theVertices.add(v7);  
		Vertex v8=new Vertex(pr,ra,0);theVertices.add(v8);   
		Vertex v9=new Vertex(-pr,ra,0);theVertices.add(v9);  
		Vertex v10=new Vertex(pr,-ra,0);theVertices.add(v10);  
		Vertex v11=new Vertex(-pr,-ra,0);theVertices.add(v11);  
		
		Face f0=new Face(v0,v1,v9); theFaces.add(f0); 
		Face f1=new Face(v0,v1,v8);theFaces.add(f1); 
		Face f2=new Face(v1,v7,v9);theFaces.add(f2); 
		Face f3=new Face(v1,v5,v8); theFaces.add(f3); 
		Face f4=new Face(v0,v4,v8); theFaces.add(f4); 
		Face f5=new Face(v0,v6,v9);theFaces.add(f5); 
		Face f6=new Face(v1,v5,v7); theFaces.add(f6); 
		Face f7=new Face(v0,v6,v4); theFaces.add(f7); 
		Face f8=new Face(v7,v9,v11);theFaces.add(f8); 
		Face f9=new Face(v6,v2,v11);theFaces.add(f9); 
		Face f10=new Face(v5,v8,v10); theFaces.add(f10); 
		Face f11=new Face(v4,v8,v10); theFaces.add(f11); 
		Face f12=new Face(v3,v5,v7);theFaces.add(f12); 
		Face f13=new Face(v3,v7,v11);theFaces.add(f13); 
		Face f14=new Face(v3,v5,v10); theFaces.add(f14); 
		Face f15=new Face(v4,v10,v2); theFaces.add(f15); 
		Face f16=new Face(v2,v4,v6);theFaces.add(f16); 
		Face f17=new Face(v2,v3,v10);theFaces.add(f17); 
		Face f18=new Face(v9,v6,v11); theFaces.add(f18); 
		Face f19=new Face(v2,v3,v11);theFaces.add(f19); 
		
	
		
	}
	
	
	
	
	public String makeMesh(){
		System.out.println("Vertices : "+theVertices.size()); 
		String s="mesh2{\n vertex_vectors{\n"+theVertices.size()+",\n";
		int j=0; 
		for(int i=0;i<theVertices.size()-1;i++){
			s+=theVertices.get(i)+",\n";
			if(j%100==0) System.out.println(j);
			j++; 
		}
		s+=theVertices.get(theVertices.size()-1)+"\n}\n";
		
		
		
		s+="face_indices{\n"+theFaces.size()+",\n";
		j=0; 
		for(int i=0;i<theFaces.size()-1;i++){
			s+=theFaces.get(i)+",\n";
			if(j%100==0) System.out.println(j);
			j++; 
		}
		s+=theFaces.get(theFaces.size()-1)+"\n}\n"; 
		s+="inside_vector <1,1,1>\n";
		
		s+="pigment{ \nimage_map{\n jpeg \"eartheqr1.jpg\" map_type 1}\n rotate "+(-angle)+"*x  }\n}\n"; 
		
		return s; 
	}
	
	public void iter(){
		ArrayList<Vertex> proVertices=new ArrayList<Vertex>();
		ArrayList<Face>proFaces=new ArrayList<Face>();
		System.out.println("Faces : "+theFaces.size()); 
		int j=0; 
		for(Face f: theFaces){
			System.out.println(j++); 
			Vertex varray[]=new Vertex[6];
			varray[0]=f.v1; 
			varray[1]=f.v2; 
			varray[2]=f.v3; 
			varray[3]=Vertex.middle(varray[1], varray[0]); 
			varray[4]=Vertex.middle(varray[1], varray[2]);
			varray[5]=Vertex.middle(varray[0], varray[2]); 
			varray[3].mulByDouble(1/varray[3].norm()); 
			varray[4].mulByDouble(1/varray[4].norm()); 
			varray[5].mulByDouble(1/varray[5].norm()); 
			for(int i=0;i<6;i++)
				if(!proVertices.contains(varray[i]))
					proVertices.add(varray[i]); 
			
			proFaces.add(new Face(varray[0],varray[3],varray[5])); 
			proFaces.add(new Face(varray[1],varray[3],varray[4])); 
			proFaces.add(new Face(varray[2],varray[4],varray[5])); 
			proFaces.add(new Face(varray[3],varray[4],varray[5])); 
			
		}
		theFaces=proFaces; 
		theVertices=proVertices; 
	}
	
	public void iterKoch(){
		ArrayList<Vertex> proVertices=new ArrayList<Vertex>();
		ArrayList<Face>proFaces=new ArrayList<Face>();
		System.out.println("Faces : "+theFaces.size()); 
		int j=0; 
		for(Face f: theFaces){
			System.out.println(j++); 
			Vertex varray[]=new Vertex[9];
			varray[0]=f.v1; 
			varray[1]=f.v2; 
			varray[2]=f.v3; 
			varray[3]=Vertex.bary(f.v1,f.v2,1/3); 
			for(int i=0;i<9;i++)
				if(!proVertices.contains(varray[i]))
					proVertices.add(varray[i]); 
			
			proFaces.add(new Face(varray[0],varray[3],varray[5])); 
			proFaces.add(new Face(varray[1],varray[3],varray[4])); 
			proFaces.add(new Face(varray[2],varray[4],varray[5])); 
			proFaces.add(new Face(varray[3],varray[4],varray[5])); 
			
		}
		theFaces=proFaces; 
		theVertices=proVertices; 
	}
	
	public static void main(String[] args) {
		GeodeGenerator gege=new GeodeGenerator();
		for(int i=0;i<3;i++){
		gege.iter();
		System.out.println("-->"+i+" faces "+gege.theFaces.size());
		}
		System.out.println("fin des iterations"); 
		try{
			PrintStream outx=new PrintStream("/tmp/outgeode.txt");
			outx.println(gege.makeMesh()); 
		}
		catch (Exception e){System.out.println(e); }
		System.out.println("done"); 
	}
}
